package crud

import (
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
)

// CRUD 通用接口
type CRUD[T any] struct {
	DB *gorm.DB
}

// Query 查询构建器
type Query[T any] struct {
	db *gorm.DB
}

// NewCRUD 创建 CRUD 实例
func NewCRUD[T any](db *gorm.DB) *CRUD[T] {
	db = db.Session(&gorm.Session{
		Logger: logger.Default.LogMode(logger.Info), // 这里设置日志级别为 Info
	})
	return &CRUD[T]{DB: db}
}
func (c *CRUD[T]) Table(tableName string) *CRUD[T] {
	return &CRUD[T]{DB: c.DB.Table(tableName)}
}

// Create 创建记录
func (c *CRUD[T]) Create(model *T) error {
	return c.DB.Create(model).Error
}

// GetByID 根据 ID 查询
func (c *CRUD[T]) GetByID(id any) (*T, error) {
	var model T
	// 使用只读模式查询，避免自动更新
	err := c.DB.Session(&gorm.Session{
		SkipHooks: true, // 跳过钩子函数
	}).First(&model, id).Error

	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, nil // 返回 nil 而不是指针，表示没有找到记录
		}
		return nil, err
	}
	return &model, nil
}

// GetByIds 根据 IDs 查询
func (c *CRUD[T]) GetByIds(ids []any) ([]T, error) {
	var models []T
	err := c.DB.Where("id IN ?", ids).Find(&models).Error
	if err != nil {
		return nil, err
	}
	return models, nil
}

// GetAll 获取所有记录，返回查询构建器
func (c *CRUD[T]) GetAll() *Query[T] {
	return &Query[T]{db: c.DB}
}

// Select 指定查询字段
func (q *Query[T]) Select(fields ...string) *Query[T] {
	q.db = q.db.Select(fields)
	return q
}

// Where 指定查询条件
func (q *Query[T]) Where(field string, value any) *Query[T] {
	q.db = q.db.Where(field+" = ?", value)
	return q
}

// Exists 判断记录是否存在
func (q *Query[T]) Exists() (bool, error) {
	var model T
	err := q.db.Limit(1).First(&model).Error
	if err != nil && err != gorm.ErrRecordNotFound {
		return false, err
	}
	return err != gorm.ErrRecordNotFound, nil
}

// Order 按指定字段排序
func (q *Query[T]) Order(field string) *Query[T] {
	q.db = q.db.Order(field)
	return q
}

// Desc 降序排序
func (q *Query[T]) Desc() *Query[T] {
	return q.Order("DESC")
}

// Asc 升序排序
func (q *Query[T]) Asc() *Query[T] {
	return q.Order("ASC")
}

// First 查询第一个记录，返回查询构建器
func (q *Query[T]) First() (*T, error) {
	var model T
	err := q.db.First(&model).Error
	return &model, err
}

// Find 执行查询并返回结果
func (q *Query[T]) Find() ([]T, error) {
	var models []T
	err := q.db.Find(&models).Error
	return models, err
}

// Update 更新记录
func (c *CRUD[T]) Update(model *T) error {
	return c.DB.Save(model).Error
}

// DeleteByID 根据 ID 删除
func (c *CRUD[T]) DeleteByID(id any) error {
	return c.DB.Delete(new(T), id).Error
}

// Updates 更新多个字段
func (c *CRUD[T]) Updates(model *T, updates map[string]any) error {
	return c.DB.Model(model).Updates(updates).Error
}

// UpdateByID 根据ID更新记录
func (c *CRUD[T]) UpdateByID(id any, model any) error {
	return c.DB.Model(new(T)).Where("id = ?", id).Updates(model).Error
}
